package thread.n8;

import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.*;

/**
 * 线程池的方法：
 *      1：execute方法：不用介绍了，运行runnable任务，就调用这个。
 *      2：submit方法：运行callable的任务，可以通过【future.get()】方法获取返回值。
 *      3：invokeAll方法：运行callable的任务。区别在于，它是运行一系列callable的集合。
 *      4：invokeAny方法：运行callable的任务，区别在于，运行callable的集合中的任一一个任务。
 *      5：shutdown方法：将线程池状态变为：SHUTDOWN。这时线程池【不会接收新的线程】、【但是会继续执行在阻塞队列中的线程】。
 *      6：shutdownNow方法：将线程状态变成：STOP，立即关闭线程池，不会执行阻塞队列中的任务，线程正在执行的任务也会被打断。
 *          shutdown和shutdownNow方法的区别。
 *              首先：它们都会修改线程池的状态为：【SHUTDOWN】、【STOP】。
 *              其次：它会会【中断（回收）】部分线程。【shutdown是回收所有空闲的线程】、【shutdownNow是回收所有的线程（这就是它为什么不会执行正在运行的任务的原因）】。
 *              最后：调用【tryTerminate】关闭线程池。
 */
public class PoolSubmitTest {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
       test1();
       test2();
       test3();
    }

    //测试invokeAny方法
    private static void test3() throws InterruptedException, ExecutionException {
        ExecutorService executorService = Executors.newFixedThreadPool(2);

        Callable c1 = new Callable() {
            @Override
            public Object call() throws Exception {
                Thread.sleep(1000);
                return "1";
            }
        };
        Callable c2 = new Callable() {
            @Override
            public Object call() throws Exception {
                Thread.sleep(2000);
                return "2";
            }
        };
        Callable c3 = new Callable() {
            @Override
            public Object call() throws Exception {
                Thread.sleep(3000);
                return "3";
            }
        };
        List<Callable<String>> callables = Arrays.asList(c1, c2, c3);
        //submit方法的使用。
        String future = executorService.invokeAny(callables);
        System.out.println(future);
    }

    //测试invokeAll方法
    private static void test2() throws InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(2);

        Callable c1 = new Callable() {
            @Override
            public Object call() throws Exception {
                Thread.sleep(1000);
                return "1";
            }
        };
        Callable c2 = new Callable() {
            @Override
            public Object call() throws Exception {
                Thread.sleep(2000);
                return "2";
            }
        };
        Callable c3 = new Callable() {
            @Override
            public Object call() throws Exception {
                Thread.sleep(3000);
                return "3";
            }
        };
        List<Callable<String>> callables = Arrays.asList(c1, c2, c3);
        //submit方法的使用。
        List<Future<String>> futures = executorService.invokeAll(callables);
        futures.forEach(i->{
            try {
                System.out.println(i.get());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        });
    }

    //测试submit方法
    private static void test1() throws ExecutionException, InterruptedException {
        ExecutorService executorService = Executors.newSingleThreadExecutor();

        //submit方法的使用。
        Future<String> future = executorService.submit(new Callable<String>() {
            @Override
            public String call() throws Exception {
                Thread.sleep(1000);
                return "ok";
            }
        });

        System.out.println("结果为："+future.get());
    }

}


interface Pool{
    // 执行任务
    void execute(Runnable command);

    // 提交任务 task，用返回值 Future 获得任务执行结果
    <T> Future<T> submit(Callable<T> task);

    // 提交 tasks 中所有任务
    <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
            throws InterruptedException;

    // 提交 tasks 中所有任务，带超时时间
    <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
                                  long timeout, TimeUnit unit)
            throws InterruptedException;

    // 提交 tasks 中所有任务，哪个任务先成功执行完毕，返回此任务执行结果，其它任务取消
    <T> T invokeAny(Collection<? extends Callable<T>> tasks)
            throws InterruptedException, ExecutionException;

    // 提交 tasks 中所有任务，哪个任务先成功执行完毕，返回此任务执行结果，其它任务取消，带超时时间
    <T> T invokeAny(Collection<? extends Callable<T>> tasks,
                    long timeout, TimeUnit unit)
            throws InterruptedException, ExecutionException, TimeoutException;
}